let context = canvas_dom.getContext('2d');
let launch_timer = null;
let worker_timer = null;
let coins = 0;
let _score = 0;
let time = 100;
let game_id = null;
let citizen_move_step = 6;
let current_level = null;
let current_tool = null;
let current_point = null;
let point_size = 60;
let current_config = null;
let tool_remove_reblock = 0.8;
let game_status = null;
let building_road = false;
let is_launch = false;
let tool_doms = {
    road_paver: document.getElementById('road_paver'),
    rebirth_gate:document.getElementById('rebirth_gate'),
    navigator:document.getElementById('navigator'),
    remove_tool:document.getElementById('remove_tool')
};
let source_src = {
    birth_point:'./images/birth_point.png',
    sun_house:'./images/sun_house.png',
    star_house:'./images/star_house.png',
    moon_house:'./images/moon_house.png',
    road_paver:'./images/road_paver.png',
    road:'./images/road.png',
    road_0:'./images/road_0.png',
    road_1:'./images/road_1.png',
    road_2:'./images/road_2.png',
    road_3:'./images/road_3.png',
    rebirth_gate:'./images/rebirth_gate.png',
    navigator:'./images/navigator.png',
    star:'./images/star.png',
    sun:'./images/sun.png',
    moon:'./images/moon.png',
    remove_tool:'./images/remove_tool.png',
    citizen:'./images/citizen.png',
};
let operation_mode_config ={
    coins:0,
    score:0
};
let config = {
    easy:{
        coins:3000,
        time:100,
        builds:{
            birth_point:1,
            sun_house: 1,
            star_house: 1,
            moon_house: 1
        }
    },
    normal:{
        coins:5000,
        time:100,
        builds:{
            birth_point:2,
            sun_house: 1,
            star_house: 1,
            moon_house: 1
        }
    },
    hard:{
        coins:8000,
        time:100,
        builds:{
            birth_point:3,
            sun_house: 2,
            star_house: 2,
            moon_house: 2
        }
    }
};
let preice = {
    road:50,
    rebirth_gate: 1000,
    navigator:500
};
let map = {
    birth_points:[],
    builds:[],
    roads:[],
    navigators:[],
    virtual_roads:[],
    rebirth_gate:[]
};
let birth_point_citizen_num = 5;
let accept_level = ['easy','normal','hard'];
let house_type = ['sun','moon','star'];
let can_remove_object = ['road','rebirth_gate','navigator'];
let accept_genrate_build_area = {
    x:[1,22],
    y:[1,10]
};
const load_image = (object,source_name = null,key_name='object')=>{
    source_name = source_name || object.type;
    let image = null;

    switch (source_name) {
        case 'road':
            image = new Image();
            image.src = source_src[source_name];
            image.onload = ()=>{
                object[key_name] = image;
            };
            object.dir_images = [];

            for(let i = 0;i<4;i++){
                let dir_image = new Image();
                dir_image.src = source_src[`road_${i}`];
                dir_image.onload = ()=>{
                    object.dir_images[i] = dir_image;
                }
            }
            break;
        default:
            image = new Image();
            image.src = source_src[source_name];
            image.onload = ()=>{
                object[key_name] = image;
            };
            break
    }

};
const draw_image = (image,x,y)=>{
    context.drawImage(image,x*point_size,y*point_size,point_size,point_size);
};
const random_route = (dirs)=>{
    return dirs[utils.Math.random(0,dirs.length-1)];
};
const game_start = ()=>{
    bind_tools_event();
    level_master();
    if (!restore()){
        console.log("生成新地图 >>>");
        generate_map()
    }
    update_score();
    update_wallet();
    worker();
    setInterval(()=>{
        store();
    },1000);
};
const bind_tools_event= ()=>{
    for (let tool_name in tool_doms){
        let tool_dom = tool_doms[tool_name];
        tool_dom.onclick = tools_onclick_event;
    }
};
const tools_onclick_event = (event)=>{
    let element = event.currentTarget;
    let tool_name = element.id;
    if ((current_tool || {}).name === tool_name){
        remove_tool_active_style();
        current_tool = null;
    }else{
        canvas_dom.style.cursor = `url(./images/${tool_name}_cur.png),auto`;
        current_tool = {name:tool_name};
        if (tool_name === 'road_paver'){
            load_image(current_tool,'road')
        }else{
            load_image(current_tool,tool_name)
        }
        remove_tool_active_style(tool_name);
        element.classList.add('active');
    }
};
const remove_tool_active_style = (except)=>{
    for (let tool_name in tool_doms){
        let tool_dom = tool_doms[tool_name];
        if (tool_name === except)continue;
        tool_dom.classList.remove('active');
    }
};
const level_master = ()=>{
    let level = localStorage.getItem('current.level');
    if (accept_level.indexOf(level) < 0){
        utils.message('Level type is invalid');
        window.location.href = './01_Level_Selection_Page.html';
        return false;
    }

    current_level = level;
    current_config = config[current_level];
    let current_record = JSON.parse(localStorage.getItem('current.record')) || {};
    coins = (current_record.coins == null ? current_config.coins:current_record.coins);
    coins += JSON.parse(localStorage.getItem('prev.coins'));
    localStorage.removeItem('prev.coins');

    _score = JSON.parse(localStorage.getItem('prev.score'));
    if (current_level === 'easy')utils.display(tool_doms.rebirth_gate,'none')
};
const restore = ()=>{
    let current_record = JSON.parse(localStorage.getItem('current.record')) || null;
    if (current_record === null)return false;
    map = current_record.map;
    for (let map_object_key_name in map){
        let objects = map[map_object_key_name];
        for (let object of objects){
            load_image(object);
            if (object.type === 'birth_point'){
                for (let destination of object.destinations){
                    load_image(destination);
                }
            }
        }
    }

    game_status = current_record.game_status;
    operation_mode_config = current_record.operation_mode_config;
    time = current_record.time;
    game_id = current_record.game_id;

    if (game_status !== null){
        game_over();
    }
    return true;
};
const generate_map = ()=>{
    game_id = Date.now();
    generate_birth_point();
    generate_builds();
};
const generate_birth_point = ()=>{
    for (let i = 0;i < current_config.builds.birth_point;i++){
        let empty_point = get_empty_point(accept_genrate_build_area);
        let birth_point = {
            type:'birth_point',
            x:empty_point.x,
            y:empty_point.y,
            destinations:[],
            object:null,
            current_citizen:null,
            citizens:[]
        };
        map.birth_points.push(birth_point);
        load_image(birth_point);
        generate_birth_point_citizen_destinations(birth_point);
    }
};
const get_empty_point = (area)=>{
    let random_point = {
        x:utils.Math.random(area.x[0],area.x[1]),
        y:utils.Math.random(area.y[0],area.y[1])
    };

    let point_info = get_point_info(random_point);
    let above_point = get_point_info({x:random_point.x,y:random_point.y-1});
    let bottom_point = get_point_info({x:random_point.x,y:random_point.y+1});
    let let_point = get_point_info({x:random_point.x-1,y:random_point.y});
    let right_point = get_point_info({x:random_point.x+1,y:random_point.y+1});

    if (point_info === false && above_point === false && bottom_point === false && let_point === false && right_point === false){
        return random_point;
    }else{
        return get_empty_point(area);
    }
};
const get_point_info = (point)=>{
    for (let key in map){
        let objects = map[key];
        for (let object of objects){
            if (object.x === point.x && object.y === point.y){
                return object;
            }
        }
    }
    return false;
};
const generate_birth_point_citizen_destinations = (birth_point)=>{
    let counter = 0;
    while (counter < birth_point_citizen_num){
        let citizen_type = house_type[utils.Math.random(0,2)];
        let destination = {
            type: citizen_type,
            object:null
        };
        load_image(destination);
        birth_point.destinations.push(destination);
        counter++;
    }
};
const generate_builds = ()=>{
    for (let build_type in current_config.builds){
        if (build_type === 'birth_point')continue;
        let build_num = current_config.builds[build_type];
        for (let i = 0; i < build_num;i++){
            let empty_point = get_empty_point(accept_genrate_build_area);
            let build = {
                type:build_type,
                x:empty_point.x,
                y:empty_point.y,
                object:null
            }
            load_image(build);
            map.builds.push(build);
        }
    }
};
const generate_citizens = ()=>{
    for(let birth_point of map.birth_points){
        birth_point.citizens = [];
        for (let destination of birth_point.destinations){
            let citizen  = {
                type:destination.type,
                object:null,
                x:birth_point.x,
                y:birth_point.y,
                coordinate:{
                    x:null,
                    y:null
                },
                rebirth:false
            };
            citizen.route = compute_citizen_move_route(birth_point,citizen.type);
            birth_point.citizens.push(citizen);
            load_image(citizen,'citizen');
            load_image(citizen,citizen.type,'target')
        }
    }
};
const update_wallet = ()=>{
    wallet_view_dom.innerText = wallet();
};
const update_score = ()=>{
    score_view_dom.innerText = score();
};
const wallet = ()=>{
    return coins+operation_mode_config.coins;
};
const score = ()=>{
    return _score + operation_mode_config.score;
};
const worker = ()=>{
    worker_timer = setInterval(()=>{
        context.clearRect(0,0,canvas_dom.width,canvas_dom.height);
        draw_object();
        draw_mouse_point();
        if (is_launch){
            citizen_move_animation();
        }
    },1000/60)
};
const draw_road = (road)=>{
    draw_image(road.object,road.x,road.y);
    let dirs = get_road_dirs(road,false);
    dirs.forEach((item,index)=>{
        if (road.dir_images === undefined)return false;
        if (item === false) return false;
        context.drawImage(road.dir_images[index],road.x*point_size,road.y*point_size,point_size,point_size)
    });

    let point_info = get_point_info({x:road.x,y:road.y-1});

    if (point_info){
        context.drawImage(road.dir_images[0],road.x*point_size,road.y*point_size,point_size,point_size)
    }
};
const draw_object = ()=>{
    for (let key in map){
        let objects = map[key];
        for (let object of objects){
            if (object.object == null)continue;
            switch (key) {
                case 'virtual_roads':
                    draw_image(object.object,object.x,object.y);
                    context.fillStyle = 'rgba(0,0,255,0.1)';
                    context.fillRect(object.x*point_size,object.y*point_size,point_size,point_size)
                    break;
                case 'birth_points':
                    draw_image(object.object,object.x,object.y);
                    object.destinations.forEach((item,index)=>{
                        context.drawImage(item.object,(object.x*point_size)-(point_size/5) + (index*((point_size/5)*1.5)),object.y*point_size,(point_size/5)*1.5,(point_size/5)*1.5);
                    });

                case 'roads':
                    draw_road(object);
                    continue;
                default:
                    draw_image(object.object,object.x,object.y);
                    break;
            }
        }
    }
};
const draw_mouse_point = ()=>{
    if (current_tool === null || current_point === null) return false;
    context.fillStyle = 'rgba(0,0,255,0.2)';
    switch (current_tool.name) {
        case 'road_paver':
            if (!place_road_rule(current_point)) context.fillStyle = 'rgba(255,0,0,0.2)';
            break;
        case 'navigator':
            if (!place_navigator_rule(current_point)) context.fillStyle = 'rgba(255,0,0,0.2)';
            break;
        case 'rebirth_gate':
            context.fillStyle = 'rgba(255,0,0,0.2)';
            if (place_rebirth_gate(current_point)) context.fillStyle = 'rgba(0,0,255,0.2)';
            break;
        case 'remove_tool':
            if (remove_point_rule(current_point)){
                context.fillStyle = 'rgba(0,0,255,0.2)';
                context.fillRect(current_point.x*point_size,current_point.y*point_size,point_size,point_size);
            }
            break;
    }
    if (current_tool.name !== 'remove_tool'){
        draw_image(current_tool.object,current_point.x,current_point.y);
        context.fillRect(current_point.x*point_size,current_point.y*point_size,point_size,point_size);
    }
};
const citizen_move_animation = ()=>{
    for (let birth_point of map.birth_points){
        birth_point.current_citizen = birth_point.citizens[birth_point.citizens.length-1] || null;
        if (birth_point.current_citizen === null && citizens_all_entry_builds()){
            game_over();
            return true;
        }

        let current_citizen = birth_point.current_citizen || null;
        if (current_citizen === null)continue;
        if (current_citizen.coordinate.x === null || current_citizen.coordinate.y === null){
            current_citizen.coordinate.x = current_citizen.x*point_size;
            current_citizen.coordinate.y = current_citizen.y*point_size;
        }

        context.drawImage(current_citizen.object,current_citizen.coordinate.x,current_citizen.coordinate.y,point_size,point_size);
        context.drawImage(current_citizen.target,current_citizen.coordinate.x+(point_size/3),current_citizen.coordinate.y,point_size/3,point_size/3);

        let current_road = current_citizen.route[0];
        if (current_citizen.route.length <= 0){
            let build = has_build(current_citizen);
            if (build === false){
                let road = has_road(current_citizen);
                if (road === false) continue;
                current_citizen.route = compute_citizen_move_route(road,current_citizen.type);
                continue;
            }
            if (build.type === `${current_citizen.type}_house`){
                operation_mode_config.coins += 100;
                operation_mode_config.score += 100;
                birth_point.citizens.splice(birth_point.citizens.indexOf(current_citizen),1);
                birth_point.current_citizen = null;
                update_wallet();
                update_score()
            }else{
                let rebirth_gate = map.rebirth_gate[0] || null;
                if (rebirth_gate === null || current_level === 'easy'){
                    operation_mode_config.score -= 100;
                    birth_point.citizens.splice(birth_point.citizens.indexOf(current_citizen),1);
                    birth_point.current_citizen = null;
                    update_score();
                }else{
                    current_citizen.x = rebirth_gate.x;
                    current_citizen.y = rebirth_gate.y;
                    current_citizen.coordinate.x = null;
                    current_citizen.route = [];
                    birth_point.current_citizen = null;
                }
            }
            continue;
        }
        let diffX = current_citizen.coordinate.x - current_road.x * point_size;
        let diffY = current_citizen.coordinate.y - current_road.y * point_size;

        diffY /= Math.abs(diffY || 1);
        diffX /= Math.abs(diffX || 1);

        current_citizen.coordinate.x -= citizen_move_step * diffX;
        current_citizen.coordinate.y -= citizen_move_step * diffY;
        if (current_road.x * point_size === current_citizen.coordinate.x && current_road.y * point_size === current_citizen.coordinate.y){
            current_citizen.route.splice(0,1);
            current_citizen.x = Math.trunc(current_citizen.coordinate.x / point_size);
            current_citizen.y = Math.trunc(current_citizen.coordinate.y / point_size);
        }

    }
};
const store = ()=>{
    let record = {game_id,time,game_status,coins,operation_mode_config,_score,map};
    localStorage.setItem('current.record',JSON.stringify(record));
    localStorage.setItem('current.level',current_level);
};
const game_over = ()=>{
    game_status =  false;
    clearInterval(launch_timer);
    clearInterval(worker_timer);

    game_status = citizens_all_entry_builds() && score() > 0;
    if (game_status){
        utils.display(game_status_win_view_dom,'block');
        utils.display(game_status_loss_view_dom,'none');
        utils.display(end_game_btn_dom,'block');
        utils.display(play_again_btn_dom,'none');
        if (current_level === 'hard'){
            utils.display(next_level_btn_dom,'none');
        }else{
            utils.display(next_level_btn_dom,'block');
        }
    }else {
        utils.display(game_status_win_view_dom,'none');
        utils.display(game_status_loss_view_dom,'block');
        utils.display(end_game_btn_dom,'none');
        utils.display(play_again_btn_dom,'block');
        utils.display(next_level_btn_dom,'none');
    }
    game_info_score_view_dom.innerText = score();
    game_info_wallet_view_dom.innerText = wallet();
    utils.display(game_over_page_dom,'flex');

};
const citizens_all_entry_builds = ()=>{
    for (let birth_point of map.birth_points){
        if (birth_point.citizens.length > 0) return false;
    }
    return true;
};
const place_road_rule = (point)=>{
    let point_info = get_point_info(point);
    return point_info === false;
};
const place_rebirth_gate_rule = (point)=>{
    let road = has_road(point);
    if (road === false) return false;
    let dirs = get_road_dirs(road);
    if (dirs.length > 1) return  false;
    return map.rebirth_gate.length <= 1;
};
const place_navigator_rule = (point)=>{
    let road = has_road(point);
    if (road  === false) return false;
    return road_is_cross(road)
};
const remove_point_rule = (point)=>{
    let point_info = get_point_info(point);
    return can_remove_object.indexOf(point_info.type) >= 0;
};
const place_virtual_road = ()=>{
    if (current_point === null || !place_road_rule(current_point))return false;
    if (wallet() - map.virtual_roads.length * preice.road < 0) {
        utils.message('Not enough coins');
        return  false;
    }
    let virtual_road = {
        type:'road',
        object:null,
        x:current_point.x,
        y:current_point.y
    };
    map.virtual_roads.push(virtual_road);
    load_image(virtual_road);
};
const place_navigator = ()=>{
    if (!place_navigator_rule(current_point))return false;
    if (wallet() - preice.navigator < 0){
        utils.message('Not enough coins');
        return false;
    }

    let navigator = {
        id:Date.now(),
        x:current_point.x,
        y:current_point.y,
        object:null,
        connect:{
            navigators:[],
            builds:[],
            roads:[]
        },
        type:'navigator'
    };
    map.navigators.push(navigator);
    load_image(navigator);
    coins -= preice.navigator;
    update_wallet();
};
const place_rebirth_gate = ()=>{
    if (!place_rebirth_gate_rule(current_point)) return false;
    if (wallet() - preice.rebirth_gate < 0){
        utils.message('Not enough coins');
        return false;
    }

    let rebirth_gate = {
        type:'rebirth_gate',
        x:current_point.x,
        y:current_point.y,
        object:null
    };

    map.rebirth_gate.push(rebirth_gate);
    load_image(rebirth_gate);
    coins -= preice.rebirth_gate;
    update_wallet();
};
const remove_point = ()=>{
    let point = has_navigator(current_point) || has_rebirth_gate(current_point) || has_road(current_point);
    if (point === false) return false;
    let objects = map[`${point.type}s`];
    let object_index = objects.indexOf(point);
    let splice_num = (object_index < 0 ? 0:1);
    coins += preice[point.type]*tool_remove_reblock;
    objects.splice(object_index,splice_num);
    update_wallet();
};
const has_road = (point)=>{
    for (let road of map.roads){
        if (road.x === point.x &&  road.y === point.y) return road;
    }
    return false;
};
const get_road_dirs = (point,format=true)=>{
    let dirs = [];
    let temp = [
        has_road({x:point.x,y:point.y-1}),  //t
        has_road({x:point.x+1,y:point.y}),  //R
        has_road({x:point.x,y:point.y+1}),  //b
        has_road({x:point.x-1,y:point.y}),  //L
    ];
    if (format){
        for (let dir of temp){
            if (dir !== false) dirs.push(dir);
        }
        return dirs;
    }else {
        return  temp;
    }
};

const virtual_road_to_real = ()=>{
    if (wallet() - map.virtual_roads.length * preice.road < 0){
        utils.message('Not enough coins');
        map.virtual_roads = [];
        return false
    }

    coins -= map.virtual_roads.length * preice.road;
    map.roads.push(...map.virtual_roads);
    map.virtual_roads = [];
    update_wallet();
};
const road_is_cross = (road,except)=>{
    let dirs = get_road_dirs(road);
    let except_index = dirs.indexOf(except);
    let splice_num = (except_index < 0 ? 0:1);
    dirs.splice(except_index,splice_num);
    if (dirs.length > 2) return dirs;
    return false;
};
const has_build = (point)=>{
    for (let build of  map.builds){
        if (build.x === point.x && build.y === point.y) return build;
    }
    return false;
};
const disable_tools = ()=>{
    for (let tool_name in tool_doms){
        tool_doms[tool_name].onclick = null;
    }

    remove_tool_active_style();
};
const above_build = (point)=>{
    let build = has_build({x:point.x,y:point.y-1});
    return (build === false ? false:build);
};
const has_navigator = (point)=>{
    for (let navigator of map.navigators){
        if (navigator.x === point.x && navigator.y === point.y) return navigator;
    }
    return false;
};
const has_rebirth_gate = (point)=>{
    let rebirth_point = map.rebirth_gate[0] || {x:null,y:null};
    if (rebirth_point.x === point.x && rebirth_point.y === point.y)return rebirth_point;
    return false;
};
const navigation = (current,dirs,target,navigator,searched_navigator = [])=>{
    if (searched_navigator.indexOf(navigator.id) >= 0)return false;
    searched_navigator.push(navigator.id);
    let target_build = `${target}_house`;

    let route = navigator_connect_target_build(navigator,target_build);
    if (route !==  false) return route;

    for (let connect_navigator_route of navigator.connect.navigators){
        let last_node = connect_navigator_route[connect_navigator_route.length -1];
        let connect_navigator = has_navigator(last_node);
        if (connect_navigator === false)return false;
        route = [];
        let navigation_route = navigation(current,dirs,target,connect_navigator,searched_navigator);
        if (navigation_route === false) return false;

        route.push(...connect_navigator_route);
        route.push(...navigation_route);
        return route
    }
    return false;
};
const navigator_connect_target_build = (navigator,target)=>{
    let routes = [];
    console.log(navigator);
    for (let route of navigator.connect.builds){
        let build = route[route.length-1];
        if (build.type === target) routes.push(route)
    }

    routes.sort((a,b)=>{
        return a.length - b.length;
    });

    return routes[0] || false;
};
const init_navigations = ()=>{
    for (let navigator of map.navigators){
        let road = has_road(navigator);
        if (road === false) continue;
        let dirs = get_road_dirs(road);

        navigator.connect.builds = [];
        navigator.connect.navigators = [];
        navigator.connect.roads = [];

        for (let dir of dirs){
            let route = compute_citizen_move_route(dir,null,road,false);
            route.unshift(dir);
            let last_node = route[route.length-1];
            switch (last_node.type){
                case 'sun_house':
                case 'moon_house':
                case 'star_house':
                    navigator.connect.builds.push(route);
                    break;
                default:
                    let last_node_navigator = has_navigator(last_node);
                    if (last_node_navigator === false){
                        navigator.connect.roads.push(route);
                    }else {
                        navigator.connect.navigators.push(route);
                    }
                    break;
            }
        }
    }
};
const compute_citizen_move_route = (current,target,form = null,auto_navigation = true)=>{
    let route = [];
    switch (current.type) {
        case 'birth_point':
            let road_node = has_road({x:current.x,y:current.y+1});
            if (road_node === false)break;
            route.push(road_node);
            route.push(...compute_citizen_move_route(road_node,target,current,auto_navigation));
            break;
            default:
                let build = above_build(current);
                if (build !== false){
                    route.push(build);
                    break;
                }

                let dirs = get_road_dirs(current);
                let except_index = dirs.indexOf(form);
                let splice_num = (except_index < 0 ? 0:1);
                dirs.splice(except_index,splice_num);
                if (dirs.length === 1){
                    let road = dirs[0];
                    route.push(road);
                    route.push(...compute_citizen_move_route(road,target,current,auto_navigation));
                }else if (dirs.length > 1){
                    if (auto_navigation){
                        let current_navigator = has_navigator(current);
                        if (current_navigator === false){
                            let road = random_route(dirs);
                            route.push(road);
                            route.push(...compute_citizen_move_route(road,target,current,auto_navigation));
                        }else{
                            let navigation_route = navigation(current,dirs,target,current_navigator);
                            if (navigation_route === false){
                                let road = random_route(dirs);
                                route.push(road);
                                route.push(...compute_citizen_move_route(road,target,current,auto_navigation));
                            }else{
                                console.log(navigation_route);
                                route.push(...navigation_route);
                            }
                        }
                    }
                }
                break;
    }
    return route;
};

next_level_btn_dom.onclick = ()=>{
    if (current_level === 'hard') return false;
    localStorage.setItem('current.level',accept_level[accept_level.indexOf(current_level)+1]);
    localStorage.setItem('prev.coins',wallet());
    localStorage.setItem('prev.score',score());
    localStorage.removeItem('current.record');
    window.location.reload();
};
end_game_btn_dom.onclick = ()=>{
    let rankings = JSON.parse(localStorage.getItem('rankings')) || [];
    rankings.forEach((item,index)=>{
        if (item.id === game_id){
            window.location.href = './01_Ranking_Page.html';
            return false;
        }
    });

    let nickname = localStorage.getItem('current.nickname');
    let ranking = {
        game_id,nickname,level:current_level,wallet:wallet(),score:score(),time,submit_at:Date.now()
    };
    rankings.push(ranking);
    localStorage.setItem('rankings',JSON.stringify(rankings));
    window.location.href = './01_Rankings_Page.html';
};
play_again_btn_dom.onclick = ()=>{
    let road_nums = map.roads.length;
    let navigator_num = map.navigators.length;
    let rebirth_gate_num = map.rebirth_gate.length;

    coins += preice.road * road_nums;
    coins += preice.navigator * navigator_num;
    coins += preice.rebirth_gate * rebirth_gate_num;

    map.roads = [];
    map.navigators = [];
    map.rebirth_gate = [];
    game_status = null;
    utils.display(game_over_page_dom,'none');
};
build_btn_dom.onclick = ()=>{
    is_launch = false;
    bind_tools_event();
    utils.display(launch_btn_dom,'flex');
    utils.display(build_btn_dom,'none');
    clearInterval(launch_timer);
    operation_mode_config.coins = 0;
    operation_mode_config.score = 0;
    update_wallet();
    update_score();
    time_view_dom.innerText = '100';
};
launch_btn_dom.onclick = ()=>{
    current_tool = current_point = null;
    disable_tools();
    utils.display(build_btn_dom,'flex');
    utils.display(launch_btn_dom,'none');

    init_navigations();
    generate_citizens();
    time = 100;
    launch_timer = setInterval(()=>{
        if (time <= 1){
            game_over();
            clearInterval(launch_timer);
        }
        time--;
        time_view_dom.innerText = time;
    },1000);
    is_launch = true;
};
setting_btn_dom.onclick = ()=>{
    setting_radio_dom.checked = !setting_radio_dom.checked;
};
canvas_dom.onmousemove = (move_event)=>{
    if (current_tool === null) return false;
    current_point = {
        x:Math.floor(move_event.offsetX / point_size),
        y:Math.floor(move_event.offsetY / point_size)
    };

    canvas_dom.onmousedown = (down_event)=>{
        switch (current_tool.name) {
            case 'road_paver':
                building_road = true;
                place_virtual_road();
                break;
            case 'navigator':
                place_navigator();
                break;
            case 'rebirth_gate':
                place_rebirth_gate();
                break;
            case 'remove_tool':
                remove_point();
                break;

        }
    };

    canvas_dom.onmouseup = (up_event)=>{
        building_road = false;
        virtual_road_to_real();
    };

    if (building_road){
        place_virtual_road();
    }
};
save_game_btn_dom.onclick = ()=>{
    let records = JSON.parse(localStorage.getItem('records')) || [];
    let current_record = JSON.parse(localStorage.getItem('current.record'));
    current_record.submit_at = Date.now();
    current_record.level = current_level;
    current_record.nickname = localStorage.getItem('current.nickname');
    records.push(current_record);
    localStorage.setItem('records',JSON.stringify(records));
    utils.message('Save game success');
};
// const place_road_rule = ()=>{}
game_start();